package com.ctyun.xstore.vod.video;

import java.io.File;
import java.io.IOException;
import java.util.List;

import com.ctyun.xstore.vod.AbstractPartUploader;
import com.ctyun.xstore.vod.ConcurrentPartUploader;
import com.ctyun.xstore.vod.SerialPartUploader;
import com.ctyun.xstore.vod.video.model.CreateVideoCompleteRequest;
import com.ctyun.xstore.vod.video.model.CreateVideoCompleteResponse;
import com.ctyun.xstore.vod.video.model.CreateVideoRequest;
import com.ctyun.xstore.vod.video.model.CreateVideoResponse;
import com.ctyun.xstore.vod.video.model.PartETag;
import com.ctyun.xstore.vod.video.model.UploadUrlsModel;
import com.ctyun.xstore.vod.video.model.VideoFileInfoBean;

public class MultiPartOperatorClient {

	/**
	 * default part size is 5M
	 */
	private static final int DEFAULT_PART_SIZE = 1024 * 1024 * 5;

	private final AbstractPartUploader partUploader;

	private final VideoClient videoClient;

	public MultiPartOperatorClient(String accessKey, String secretKey) {
		this.videoClient = new VideoClient(accessKey, secretKey);
		this.partUploader = new ConcurrentPartUploader();
	}

	public MultiPartOperatorClient(String host, String accessKey, String secretKey) {
		this.videoClient = new VideoClient(host, accessKey, secretKey);
		partUploader = new ConcurrentPartUploader();
	}

	public MultiPartOperatorClient(String accessKey, String secretKey, int maxThreadCount) {
		this.videoClient = new VideoClient(accessKey, secretKey);
		if (maxThreadCount < 2) {
			this.partUploader = new SerialPartUploader();
		} else {
			partUploader = new ConcurrentPartUploader(maxThreadCount);
		}
	}

	public MultiPartOperatorClient(String host, String accessKey, String secretKey, int maxThreadCount) {
		this.videoClient = new VideoClient(host, accessKey, secretKey);
		if (maxThreadCount < 2) {
			this.partUploader = new SerialPartUploader();
		} else {
			partUploader = new ConcurrentPartUploader(maxThreadCount);
		}
	}

	public CreateVideoCompleteResponse multiPartUpload(File file) throws IOException {
		return this.multiPartUpload(file, DEFAULT_PART_SIZE);
	}

	public CreateVideoCompleteResponse multiPartUpload(File file, int partSize) throws IOException {
		if (file == null || !file.exists()) {
			throw new IllegalArgumentException("param error:file is null or file is not exist!");
		}
		String name = file.getName();
		long length = file.length();
		VideoFileInfoBean fileInfo = new VideoFileInfoBean(length, partSize);

		CreateVideoRequest initRequest = new CreateVideoRequest(name, fileInfo);
		CreateVideoResponse initResponse = this.videoClient.createVideo(initRequest);
		if (!initResponse.isExecuteSuccess()) {
			throw new IllegalStateException("init upload error: " + initResponse.getMessage());
		}
		UploadUrlsModel initData = initResponse.getData();
		List<String> urls = initData.getUploadUrls();
		String videoId = initData.getVideoId();

		List<PartETag> etags = doMultiPartUpload(file, fileInfo, urls);

		CreateVideoCompleteRequest completeRequest = new CreateVideoCompleteRequest();
		completeRequest.setVideoId(videoId);
		completeRequest.setEtags(etags);
		return this.videoClient.createVideoComplete(completeRequest);
	}

	public List<PartETag> doMultiPartUpload(File file, VideoFileInfoBean fileInfo, List<String> urls)
			throws IOException {
		fileInfo.validateParam();
		return partUploader.multiPartupload(file, urls, fileInfo.getPartSize());
	}

}
